//`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
module MutMosi(
	input			clk_in,     //100M时钟
	input			rst_n,
	input			tx_en,
	input	[15:0]	CMD,			//地址
	input	[31:0]	DATA,			//待传输数据
	output	reg		CS,
	output	reg		SPI_SCLK,
	output	reg		SPI_SDO
);
//16个地址时钟 32个数据时钟 最好还有8个时钟
parameter READY		= 4'd1;
parameter IDLE		= 4'd2;
parameter data_CMD	= 4'd4;
parameter SCLK_L	= 4'd5;
parameter data_DATA	= 4'd7;
parameter OVER1		= 4'd10;
parameter OVER		= 4'd11;

reg[3:0] state;
reg[1:0] cnt_4;
reg[7:0] cnt_CMD;
reg[7:0] cnt_data;
reg[7:0] cnt_OVER1;

reg[4:0] cnt_8;
reg[4:0] cnt_5;
always@(posedge clk_in or negedge rst_n)
begin
	if(!rst_n)
		cnt_8	<= 5'd0;
	else if(cnt_8 == 'd5)
		cnt_8	<= cnt_8;
	else if(state == IDLE)
		cnt_8	<= cnt_8 + 1'b1;
	else
		cnt_8	<= 5'd0;
end

reg en_0,en_1;
wire en_pos;
//wire en_neg;
reg[7:0] SCLK_LL;
always@(posedge clk_in or negedge rst_n)
begin
	if(!rst_n)
	begin
		{en_1,en_0} <= 2'b00;
	end
	else
	begin
		{en_1,en_0} <= {en_0,tx_en};
	end
end

assign en_pos = ((~en_1) & (en_0)) ? 1'b1 : 1'b0;  /* 取上升沿 */
//assign en_neg = ((~en_0) & (en_1)) ? 1'b1 : 1'b0;  /* 取下降沿 */
always@(posedge clk_in or negedge rst_n)
begin
	if(!rst_n)
	begin
		CS		<= 1;
		SPI_SDO	<= 0;
		state	<= READY;
		cnt_5	<= 0;
		SCLK_LL	<= 0;
	end
	else
	begin
		case(state)
		READY:begin
			if(en_pos)
			begin
				CS		<= 0;
				SPI_SDO	<= 0;
				state	<= IDLE;
				SCLK_LL	<= 0;
			end
			else
			begin
				CS		<= 1;
				SPI_SDO	<= 0;
				state	<= READY;
				SCLK_LL	<= 0;
			end
		end
		IDLE:begin
			if(cnt_8 == 'd5)
			begin
				state	<= data_CMD;
				cnt_CMD	<= 'd15;
				cnt_data<= 'd31;
				cnt_OVER1<= 'd7;
			end
		end
		data_CMD:begin
			if(cnt_4 == 'd2)
			begin
				CS	<= 0;
				if(cnt_CMD > 'd0)
				begin
					SPI_SDO	<= CMD[cnt_CMD];
					cnt_CMD	<= cnt_CMD - 8'd1;
				end
				else
				begin
					SPI_SDO	<= CMD[0];
					state	<= SCLK_L;
				end
			end
		end
		SCLK_L:begin
			if(SCLK_LL > 'd20)
			begin
				SCLK_LL	<= 0;
				state	<= data_DATA;
				CS		<= 0;
			end
			else if(SCLK_LL == 'd4)
			begin
				state	<= SCLK_L;
				SCLK_LL	<= SCLK_LL + 8'd1;
				CS		<= 0;
				SPI_SDO	<= 0;
			end
			else
			begin
				CS		<= 0;
				SCLK_LL	<= SCLK_LL + 8'd1;
				state	<= SCLK_L;
			end
		end
		data_DATA:begin
			if(cnt_4 == 'd2)
			begin
				CS	<= 0;
				if(cnt_data > 'd0)
				begin
					SPI_SDO	<= DATA[cnt_data];
					cnt_data<= cnt_data - 8'd1;
				end
				else
				begin
					SPI_SDO	<= DATA[0];
					state	<= OVER1;
				end
			end
		end
		OVER1:begin
			if(cnt_4 == 'd2)
			begin
				CS	<= 0;
				if(cnt_OVER1 > 'd0)
				begin
					SPI_SDO	<= 0;
					cnt_OVER1<= cnt_OVER1 - 8'd1;
				end
				else
				begin
					SPI_SDO	<= 0;
					state	<= OVER;
					CS		<= 0;
				end
			end
		end
		OVER:begin
			if(cnt_5=='d4)
			begin
				CS		<= 1;
				SPI_SDO	<= 0;
				state	<= READY;
				cnt_5	<= 0;
			end
			else
			begin
				cnt_5	<= cnt_5 + 5'd1;
				CS		<= 0;
				SPI_SDO	<= 0;
				state	<= state;
			end
		end
		default:begin
			SPI_SDO	<= 0;
			state	<= READY;
			CS		<= 1;
		end
		endcase
	end
end

always@(posedge clk_in or negedge rst_n)
begin
	if(!rst_n)
		SPI_SCLK	<= 1'b0;
	else if(cnt_4 == 'd0)
		SPI_SCLK	<= 1'b0;
	else if(cnt_4 == 'd2)
		SPI_SCLK	<= 1'b1;
	else
		SPI_SCLK	<= SPI_SCLK;
end

always@(posedge clk_in or negedge rst_n)
begin
	if(!rst_n)
		cnt_4	<= 'd0;
	else if(state == data_CMD )
		cnt_4	<= cnt_4 + 1'b1;
	else if(state == data_DATA )
		cnt_4	<= cnt_4 + 1'b1;
	else if(state == OVER1 )
		cnt_4	<= cnt_4 + 1'b1;
	else
		cnt_4	<= 0;
end

endmodule


